package cn.murky.tenant.filter;

import cn.murky.common.constant.CommonErrorConstant;
import cn.murky.common.utils.StringUtils;
import cn.murky.core.exception.MurkyException;
import cn.murky.core.web.ApiResult;
import cn.murky.tenant.core.SecurityTenantUserInfo;
import cn.murky.tenant.core.utils.SecurityUtils;
import cn.murky.tenant.system.api.TenantUserApi;
import cn.murky.tenant.system.api.domain.bo.TenantUserBO;
import lombok.extern.slf4j.Slf4j;
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Inject;
import org.noear.solon.core.handle.Context;
import org.noear.solon.core.handle.FilterChain;
import org.noear.solon.core.handle.Filter;

import java.util.List;

import static cn.murky.tenant.core.constant.Constants.TENANT_ID_HEADER;

@Component(index = 1)
@Slf4j
public class TenantFilter implements Filter {
    @Inject("${security.path-ignore}")
    private List<String> ignoreList;
    @Inject
    private TenantUserApi tenantUserApi;

    @Override
    public void doFilter(Context ctx, FilterChain chain) throws Throwable {
        SecurityTenantUserInfo userInfo = null;
        if (!ignoreList.contains(ctx.uri().getPath())) {
            String tenantId = ctx.header(TENANT_ID_HEADER);
            if (StringUtils.isEmpty(tenantId)) {
                log.info("[TenantFilter] -> 此次请求未携带租户id ip:{},method:{},uri:{}", ctx.realIp(), ctx.method(), ctx.uri());
                ctx.render(ApiResult.fail(CommonErrorConstant.NOT_LOGIN));
                return;
            }
            userInfo = SecurityUtils.callTenantId(Long.parseLong(tenantId), SecurityUtils::getUserInfoNoScope);
            if (userInfo != null) {
                if (!userInfo.getTenantId().toString().equals(tenantId)) {
                    log.info("[TenantFilter] -> 无该租户访问权限user_id:{},tenant_id:{} ip:{},method:{},uri:{}", userInfo.getUserId(), tenantId, ctx.realIp(), ctx.method(), ctx.uri());
                    ctx.render(ApiResult.fail(CommonErrorConstant.NOT_TENANT_PREMISSION));
                    return;
                }
            } else {
                Long userId = SecurityUtils.callTenantId(Long.parseLong(tenantId), SecurityUtils::getUserId);
                TenantUserBO tenantUserBO = tenantUserApi.getById(userId);
                if (tenantUserBO == null) {
                    log.info("[TenantFilter] -> 疑似非法请求 ip:{},method:{},uri:{}", ctx.realIp(), ctx.method(), ctx.uri());
                    ctx.render(ApiResult.fail(CommonErrorConstant.FAIL));
                    return;
                }
                if (!tenantUserBO.getFkTenantId().toString().equals(tenantId)) {
                    log.info("[TenantFilter] -> 无该租户访问权限id:{} ip:{},method:{},uri:{}", tenantId, ctx.realIp(), ctx.method(), ctx.uri());
                    ctx.render(ApiResult.fail(CommonErrorConstant.NOT_TENANT_PREMISSION));
                    return;
                }
            }
        }
        SecurityUtils.runnable(userInfo, () -> {
            try {
                chain.doFilter(ctx);
            } catch (Throwable e) {
                throw new MurkyException(e);
            }
        });
    }
}
